// new 和malloc 的时候（操作系统给的是延迟开辟），并不是new以及malloc之后立即把内存给你,给的是你的虚拟空间，而是在你对这段空间进行访问的时候，才会给你,在访问这段空间的时候会发生缺页中断
//缺页中断：在页表和实际地址的转换时，如果实际地址没有被开辟出来的话，OS会停止手头上的任务，去开辟物理空间
//new 和 malloc也是延迟开辟，在创建的时候不给你空间，用的时候在给你构建对象
#include <iostream>
#include <pthread.h>
#include <string.h>
#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <functional>

namespace threadNs
{

    const int num = 1024;
    //using func_t = std::function<void *(void *)>; // 包装器，把void*(void*)的函数指针包装成func_t
    typedef std::function<void*(void*)> func_t;
    class Thread
    {
    private:
        // 在类内创建，想让线程执行对应的方法，需要将方法设置为static
        static void *static_routine(void *args)
        // 非静态成员的话，类内第一个参数是this指针，这里会报错因为对应pthread_create的函数指针只允许有一个参数
        // 静态方法不能调用成员成员函数和成员变量
        {
            Thread* bq = static_cast<Thread *>(args);
            bq->callBack();  
        }

    public:
        // 构造函数
        Thread()
        {
            char buffer[num];
            snprintf(buffer, sizeof buffer, "thread->%d",numThread_++);
            name_ = buffer;  //把名字付给name_参数
        }

        void start(func_t func, void *args=nullptr)
        {
            func_ = func;
            args_ = args;
            int n = pthread_create(&tid_, nullptr, static_routine, this);
            assert(n == 0); // 在意料之中的错误使用assert，在release（会对代码进行一些优化）的版本下，assert不执行          // 异常 ==if  意料之外用异常或者if判断
            (void)n;
        }

        void join()
        {
            int n = pthread_join(tid_, nullptr);
            assert(n == 0);
            (void)n;
        }

        void *callBack() { return func_(args_); }
        
        std::string threadName(){ return name_; }

        ~Thread() {}

    private:
        std::string name_;
        func_t func_;
        void *args_;
        pthread_t tid_;
        static int numThread_;
    };
    int Thread::numThread_=1;


}

//end namespace threadNs
